package BNS.graphs;

import java.awt.Component;
import java.util.Date;
import java.util.Random;

import javax.swing.JOptionPane;


/** an extension to the Graph class that provides a way of generating 
	a Graph in the following way:<br/>
	First, "size" nodes are created in a conceptual ring (cycle).<br/>
	Second, each node is connected to its nearest "adj" nodes beside it in the ring.
	Each node therefor acquires 2*adj neighbours.<br/>
	Third, "chords" new edges are added between nodes that are not yet connected.<br/>
	The total number of edges is therefor size*adj+chords.
	*/
public class RingChordGraph extends AnnotatedGraph {
	// TODO: remove these special annotation values and put them in Properties
	//		(See notes in Graph and AnnotatedGraph.)
	
	/**
   * 
   */
  private static final long serialVersionUID = 1L;
  public final String params, comment;
	public final int chromaticNumber, diameter, dominationRadius;
	public final double clusterQuotient;
	public final java.util.Date creationDate;
	//private static final long serialVersionUID = 01L;// to suppress warning
	
	/** returns a String containing various factoids about this graph,
		composed from the various annotation variables.
		Intended only for human consumption. 
		TODO: This method should be replaced by access to Graph properties.
		*/
	public String getInfo() {
		return params +" "+ comment +"\n"
		+" chromaticNumber="+ chromaticNumber
		+" diameter="+ diameter
		+" date= "+ creationDate;
		}
	
	/** a driver to test the other methods in this class.
		It requires 3 parameters: adj, size and chords.
		(See similarly named parameters for in class notes.)
		If they appear on the command line, they will be used;
		otherwise a GUI pane will appear to prompt the user for them.
		In either case, stuff is printed but not saved anywhere.
		*/
	public static void main(String[] args) {
		RingChordGraph gr;
		if (args.length>=3) {
			int adj= Integer.parseInt(args[0]);
			int size= Integer.parseInt(args[1]);
			int redo= Integer.parseInt(args[2]);
			// TODO: pack remaining args into comment
			gr= new RingChordGraph(adj, size, redo, "test");
			}
		else gr= create(null);
		if (gr!=null) {
			if(gr.numNodes()<20) gr.prettyPrint(System.err);
			else gr.histoDegrees(System.err);
			}
		else System.err.println("null graph");
		}
	
	/** sets up a GUI dialog to obtain the needed parameters,
		then constructs a RingChordGraph using them and returns it.
		*/
	public static RingChordGraph create(Component frame) {
		try {
			String params= (String)JOptionPane.showInputDialog(frame, 
			   "enter 3 parameters separated by commas:\n"
			   +"adj,size,chords",
			   "Creating Ring&Chords Graph",
			   JOptionPane.QUESTION_MESSAGE);
			String[] param= params.split(",");
			int adj= Integer.parseInt(param[0]);
			int size= Integer.parseInt(param[1]);
			int chords= Integer.parseInt(param[2]);
			String comment="test";
			if (param.length>3) comment=param[3];
			return new RingChordGraph(adj, size, chords, comment);
			}
		catch (Exception e) { return null; }
		}
	
	/** creates a random graph starting with a ring graph and adding
		a given number of extra chords to it. See class notes.
		@param adj the number of connected neighbours on either side
		@param size the total number of nodes wanted
		@param chords the total number of new edges laid across the ring
		@param comment used to describe the purpose of the graph
		*/
	public RingChordGraph(int adj, int size, int chords, String comment) {
		super(size, size*adj+chords);
		System.err.println("generating RingChordGraph "+ adj +", "+ size +", "+ chords);
		creationDate= new Date();
		this.params= adj +","+ size +","+ chords;
		this.comment= comment;
		
		Random rand= new Random();
		Node[] nod= new Node[size];
		// Note '?' and 0 are default values for node class and status quo color, respectively.;
		for(int t=0; t<size; t++) nod[t]= addNode("n"+(t+1), '?', 0);
		for(int t=0; t<size; t++) 
			for(int a=1; a<=adj; a++)
				addEdge(nod[t],nod[(t+a)%size]);
		for(int reE=0; reE<chords; reE++) {
			int rn= rand.nextInt(size);
			int rd= rand.nextInt(size-2*adj-1);	// exclude itself and adjacents
			rd= (rn+adj+(rd+1))%size;
			System.err.println("new chord "+reE +" from node "+ rn +" to "+ rd);
			if (addEdge(nod[rn],nod[rd])==null) {
				System.err.println("duplicate edge not added to graph");
				reE--;
				}
			}
		chromaticNumber= 0;			// TODO: make this meaningful
		diameter= 0;				// TODO: make this meaningful
		dominationRadius= 0;		// TODO: make this meaningful
		clusterQuotient= 0.;		// TODO: make this meaningful
		//System.err.println("RingChordGraph generated graph");
		}
	
	}
